#include <pthread.h>
#include <vector>
#include <queue>
#include <cstdio>
#include <unistd.h>
#include "thread.h"
using namespace std;

//线程池：注线程只管往线程池里派发任务，线程池解决完后返回，你什么都不用管



// class ThreadPool
// {
//     int pop()
//     {
//         pthread_mutex_lock(&_mutex);
//         while(_bq.size() == 0)
//         {
//             pthread_cond_wait(&_c_cond, &_mutex);
//         }
//         int data = _bq.front();
//         _bq.pop();
//         pthread_cond_signal(&_p_cond);
//         pthread_mutex_unlock(&_mutex);
//         return data;
//     }

// public:
//     ThreadPool(int pthread_size = 5, int maxcap = 5)  
//         :_threads(pthread_size)
//         ,_pthread_size(pthread_size)
//         ,_maxcap(maxcap)
//         {
//             pthread_mutex_init(&_mutex, nullptr);
//             pthread_cond_init(&_c_cond, nullptr);
//             pthread_cond_init(&_p_cond, nullptr);  
//         }
    
//     void start()
//     {
//         for(int i = 0; i < _pthread_size; ++i)
//         {
//             pthread_create(&_threads[i], nullptr, HandlerTask, this);
//         }
//     }


//     static void* HandlerTask(void* argv)
//     {
//         ThreadPool* bq = static_cast<ThreadPool*>(argv);
//         while(1)
//         {
//             int data = bq->pop();
//             printf("data: %d\n", data);
//             sleep(3);
//         }
//         return nullptr; 
//     }


//     void push(int data)
//     {
//         pthread_mutex_lock(&_mutex);
//         while(_bq.size() == _maxcap)
//         {
//             pthread_cond_wait(&_p_cond, &_mutex);
//         }
//         _bq.push(data);
//         pthread_cond_signal(&_c_cond);
//         pthread_mutex_unlock(&_mutex);
//     }

//     ~ThreadPool()
//     {
//         pthread_mutex_destroy(&_mutex);
//         pthread_cond_destroy(&_c_cond);
//         pthread_cond_destroy(&_p_cond);
//         //for(int i = 0; i < _pthread_size; ++i)
//         // {
//         //     pthread_cancel(_threads[i]);
//         // }
//     }

// private:
//     // 管理线程
//     vector<pthread_t> _threads;
//     int _pthread_size;

//     pthread_mutex_t _mutex;
//     pthread_cond_t _c_cond;
//     pthread_cond_t _p_cond;
    
//     queue<int> _bq;
//     int _maxcap;

// };


//单例模式 懒汉模式
template<class T>
class ThreadPool
{
private:
    int pop()
    {
        pthread_mutex_lock(&_mutex);
        while(_bq.size() == 0)
        {
            pthread_cond_wait(&_c_cond, &_mutex);
        }
        T data = _bq.front();
        _bq.pop();
        pthread_cond_signal(&_p_cond);
        pthread_mutex_unlock(&_mutex);
        return data;
    }

    ThreadPool(int pthread_size, int maxcap)  
        :_pthread_size(pthread_size)
        ,_maxcap(maxcap)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_c_cond, nullptr);
        pthread_cond_init(&_p_cond, nullptr);  
        for(int i = 0; i < pthread_size; ++i)
        {
            _threads.emplace_back(HandlerTask, this);
        }
    }

    ThreadPool(const ThreadPool& tp) = delete;
    ThreadPool& operator=(const ThreadPool& tp) = delete;

public:
    void start()
    {
        for(int i = 0; i < _pthread_size; ++i)
        {
            _threads[i].run();
        }
    }


    static void* HandlerTask(void* argv)
    {
        ThreadPool* bq = static_cast<ThreadPool*>(argv);
        while(1)
        {
            T data = bq->pop();

            printf("data: %d\n", data);
            sleep(3);
        }
        return nullptr; 
    }


    void push(const T& data)
    {
        pthread_mutex_lock(&_mutex);
        while(_bq.size() == _maxcap)
        {
            pthread_cond_wait(&_p_cond, &_mutex);
        }
        _bq.push(data);
        pthread_cond_signal(&_c_cond);
        pthread_mutex_unlock(&_mutex);
    }

    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_c_cond);
        pthread_cond_destroy(&_p_cond);
     
    }

    static ThreadPool<T>* create(int pthread_size = 5, int maxcap = 5)
    {
        if(p != nullptr)
            return p;

        pthread_mutex_lock(&lock);
        if(p == nullptr)
        {
            printf("log: singleton create done first!\n");
            p = new ThreadPool<T>(pthread_size, maxcap);
        }
        pthread_mutex_unlock(&lock);
        return p;
    }

private:
    // 管理线程
    vector<Thread> _threads;
    int _pthread_size;

    pthread_mutex_t _mutex;
    pthread_cond_t _c_cond;
    pthread_cond_t _p_cond;
    
    queue<T> _bq;
    int _maxcap;

    static ThreadPool* p;
    static pthread_mutex_t lock;

};

template<class T>
ThreadPool<T>* ThreadPool<T>::p = nullptr;

template<class T>
pthread_mutex_t ThreadPool<T>::lock = PTHREAD_MUTEX_INITIALIZER;